from flask import Flask, render_template, request, jsonify, session
import pandas as pd
import os
import random
from collections import defaultdict
# 导入配置文件
import config

app = Flask(__name__)
app.secret_key = config.SECRET_KEY  # 从配置文件读取密钥

# 读取Excel文件并处理数据
def load_questions():
    file_path = config.QUESTIONS_FILE_PATH
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"错误: 文件 {file_path} 不存在")
    
    all_questions = []
    question_id = 1  # 用于唯一标识每个问题
    
    # 加载单选题
    df_single = pd.read_excel(file_path, sheet_name='单选题')
    for _, row in df_single.iterrows():
        try:
            question = {
                'id': question_id,
                'type': '单选题',
                'content': str(row['试题正文']),  # 确保转换为字符串
                'options': {}
            }
            # 添加选项，增加错误处理
            for col in ['A', 'B', 'C', 'D', 'E', 'F']:
                if col in row and pd.notna(row[col]):
                    question['options'][col] = str(row[col])
            question['answer'] = str(row['试题答案'])
            all_questions.append(question)
            question_id += 1
        except Exception as e:
            print(f"加载单选题时出错: {e}")
    
    # 加载多选题
    df_multiple = pd.read_excel(file_path, sheet_name='多选题')
    for _, row in df_multiple.iterrows():
        try:
            question = {
                'id': question_id,
                'type': '多选题',
                'content': str(row['试题正文']),  # 确保转换为字符串
                'options': {}
            }
            # 添加选项，增加错误处理
            for col in ['A', 'B', 'C', 'D', 'E', 'F']:
                if col in row and pd.notna(row[col]):
                    question['options'][col] = str(row[col])
            question['answer'] = str(row['试题答案'])
            all_questions.append(question)
            question_id += 1
        except Exception as e:
            print(f"加载多选题时出错: {e}")
    
    # 加载判断题
    df_judgment = pd.read_excel(file_path, sheet_name='判断题')
    for _, row in df_judgment.iterrows():
        try:
            question = {
                'id': question_id,
                'type': '判断题',
                'content': str(row['试题正文']),  # 确保转换为字符串
                'options': {'对': '正确', '错': '错误'},
                'answer': str(row['试题答案'])
            }
            # 如果有解释，也添加到问题中
            if '解释' in row and pd.notna(row['解释']):
                question['explanation'] = str(row['解释'])
            all_questions.append(question)
            question_id += 1
        except Exception as e:
            print(f"加载判断题时出错: {e}")
    
    return all_questions

# 判题函数
def check_answer(user_answer, correct_answer, question_type):
    # 确保correct_answer是字符串类型
    if not isinstance(correct_answer, str):
        correct_answer = str(correct_answer)
    
    if question_type == '判断题':
        # 对于判断题，前端发送的是数组，需要转换为字符串
        if isinstance(user_answer, list):
            if user_answer:
                user_answer = str(user_answer[0])
            else:
                return False
        # 转换为字符串进行比较
        user_answer = str(user_answer)
        # 去除空白字符进行比较，提高兼容性
        return user_answer.strip() == correct_answer.strip()
    
    elif question_type == '单选题':
        # 对于单选题，前端发送的是数组，需要转换为字符串
        if isinstance(user_answer, list):
            if user_answer:
                user_answer = str(user_answer[0])
            else:
                return False
        # 转换为字符串进行比较
        user_answer = str(user_answer)
        # 去除空白字符进行比较，提高兼容性
        return user_answer.strip() == correct_answer.strip()
    
    elif question_type == '多选题':
        # 对于多选题，我们需要将答案排序后比较
        # 假设correct_answer是类似'ABC'的字符串，user_answer是包含选项的列表
        if isinstance(user_answer, list):
            # 确保所有选项都是字符串并去除空白
            user_answer_clean = [str(opt).strip() for opt in user_answer if str(opt).strip()]
            # 确保正确答案是字符串
            correct_answer = str(correct_answer)
            # 将正确答案转换为字符列表
            correct_answer_list = [char for char in correct_answer if char.strip()]
            # 排序后比较
            return sorted(user_answer_clean) == sorted(correct_answer_list)
        else:
            return False
    
    return False

# 初始化应用时加载题目
try:
    app.questions = load_questions()
    print(f"成功加载了 {len(app.questions)} 个题目")
except Exception as e:
    print(f"加载题目时出错: {str(e)}")
    app.questions = []

@app.route('/')
def index():
    # 初始化会话
    if 'current_question' not in session:
        session['current_question'] = 0
    if 'score' not in session:
        session['score'] = 0
    if 'answers' not in session:
        session['answers'] = {}
    if 'question_order' not in session:
        session['question_order'] = list(range(1, len(app.questions) + 1))  # 默认顺序
    if 'question_type_filter' not in session:
        session['question_type_filter'] = []  # 默认不过滤
    if 'filtered_questions' not in session:
        # 获取所有问题类型
        question_types = ['单选题', '多选题', '判断题']
    
    return render_template('index.html', 
                         total_questions=len(app.questions),
                         current_question=session['current_question'] + 1,
                         question_types=['单选题', '多选题', '判断题'])

@app.route('/set_filter', methods=['POST'])
def set_filter():
    data = request.json
    selected_types = data.get('types', [])
    session['question_type_filter'] = selected_types
    
    # 根据筛选条件获取符合条件的问题ID列表
    if selected_types:
        filtered_ids = [q['id'] for q in app.questions if q['type'] in selected_types]
    else:
        filtered_ids = list(range(1, len(app.questions) + 1))
    
    session['filtered_questions'] = filtered_ids
    session['question_order'] = filtered_ids.copy()  # 初始为筛选后的顺序
    session['current_question'] = 0  # 重置当前问题
    session['score'] = 0  # 重置分数
    session['answers'] = {}  # 重置答案记录
    
    return jsonify({
        'filtered_count': len(filtered_ids),
        'has_questions': len(filtered_ids) > 0
    })

@app.route('/shuffle_questions')
def shuffle_questions():
    # 获取筛选后的问题列表
    filtered_ids = session.get('filtered_questions', list(range(1, len(app.questions) + 1)))
    
    # 打乱问题顺序
    random.shuffle(filtered_ids)
    session['question_order'] = filtered_ids
    session['current_question'] = 0  # 重置当前问题
    session['score'] = 0  # 重置分数
    session['answers'] = {}  # 重置答案记录
    
    return jsonify({
        'shuffled': True,
        'total_questions': len(filtered_ids)
    })

@app.route('/question/<int:question_id>')
def get_question(question_id):
    # 确保问题ID在有效范围内
    if 1 <= question_id <= len(app.questions):
        question = app.questions[question_id - 1]
        return jsonify(question)
    else:
        return jsonify({'error': '问题不存在'}), 404

@app.route('/submit_answer', methods=['POST'])
def submit_answer():
    data = request.json
    question_id = data.get('question_id')
    user_answer = data.get('answer')
    
    if not question_id or user_answer is None:
        return jsonify({'error': '缺少必要参数'}), 400
    
    # 找到对应的问题
    if 1 <= question_id <= len(app.questions):
        question = app.questions[question_id - 1]
        is_correct = check_answer(user_answer, question['answer'], question['type'])
        
        # 保存用户答案，确保question_id是字符串类型以避免序列化错误
        question_id_str = str(question_id)
        session['answers'][question_id_str] = {
            'user_answer': user_answer,
            'is_correct': is_correct
        }
        
        # 更新分数
        if is_correct and question_id_str not in [ans for ans, data in session['answers'].items() if data['is_correct']]:
            session['score'] += 1
        
        # 不在这里更新current_question，让next路由来管理当前问题索引
        
        return jsonify({
            'correct': is_correct,
            'correct_answer': question['answer'],
            'next_question': None,  # 不在这里决定下一题，让next路由处理
            'score': session['score'],
            'explanation': question.get('explanation', '')
        })
    else:
        return jsonify({'error': '问题不存在'}), 404

@app.route('/next')
def next_question():
    # 获取当前问题索引
    current_idx = session.get('current_question', 0)
    question_order = session.get('question_order', list(range(1, len(app.questions) + 1)))
    
    if current_idx < len(question_order):
        # 下一个问题是问题顺序列表中的下一个ID
        session['current_question'] = current_idx + 1
        return jsonify({
            'next_question': question_order[current_idx] if current_idx < len(question_order) else None,
            'has_next': current_idx + 1 < len(question_order),
            'has_prev': current_idx > 0,
            'current_index': current_idx + 1,
            'total_questions': len(question_order)
        })
    else:
        return jsonify({
            'next_question': None,
            'has_next': False,
            'has_prev': current_idx > 0,
            'final_score': session.get('score', 0),
            'total_questions': len(question_order)
        })

@app.route('/previous')
def previous_question():
    # 获取当前问题索引
    current_idx = session.get('current_question', 0)
    question_order = session.get('question_order', list(range(1, len(app.questions) + 1)))
    
    # 计算上一题的索引
    prev_idx = current_idx - 2  # 减2因为当前索引指向下一个要显示的问题
    
    if prev_idx >= 0 and prev_idx < len(question_order):
        # 更新当前问题索引
        session['current_question'] = prev_idx + 1
        return jsonify({
            'previous_question': question_order[prev_idx],
            'has_prev': prev_idx > 0,
            'has_next': True,
            'current_index': prev_idx + 1,
            'total_questions': len(question_order)
        })
    elif prev_idx < 0:
        # 已经是第一题了
        return jsonify({
            'previous_question': None,
            'has_prev': False,
            'has_next': len(question_order) > 0,
            'current_index': 1,
            'total_questions': len(question_order)
        })
    else:
        return jsonify({
            'previous_question': None,
            'has_prev': False,
            'has_next': False,
            'current_index': current_idx,
            'total_questions': len(question_order)
        })

@app.route('/goto/<int:question_number>', methods=['POST'])
def goto_question(question_number):
    # 获取问题顺序列表
    question_order = session.get('question_order', list(range(1, len(app.questions) + 1)))
    
    # 检查题号是否在有效范围内
    if 1 <= question_number <= len(question_order):
        # 设置当前问题索引为请求的题号-1
        session['current_question'] = question_number
        
        # 获取对应的问题ID
        question_id = question_order[question_number - 1]
        
        return jsonify({
            'question_id': question_id,
            'has_prev': question_number > 1,
            'has_next': question_number < len(question_order),
            'current_index': question_number,
            'total_questions': len(question_order)
        })
    else:
        return jsonify({'error': '题号超出范围'}), 400

@app.route('/reset')
def reset_quiz():
    # 重置所有会话数据
    session['current_question'] = 0
    session['score'] = 0
    session['answers'] = {}
    # 重置问题顺序为默认顺序
    filtered_ids = session.get('filtered_questions', list(range(1, len(app.questions) + 1)))
    session['question_order'] = filtered_ids.copy()
    return jsonify({'success': True})

if __name__ == '__main__':
    # 确保templates目录存在
    if not os.path.exists('templates'):
        os.makedirs('templates')
    app.run(debug=config.DEBUG, host=config.HOST, port=config.PORT)